package edu.isistan.matching.adapters;

import java.util.HashMap;


import org.apache.log4j.Logger;

import edu.isistan.matching.structures.elements.TypeElement;
import edu.isistan.metamodel.DataType;

/**
 * Factory de instancias de adaptadores
 * @author Mariano
 *
 */
public class AdapterFactory {

	static Logger logger = Logger.getLogger(AdapterFactory.class);
	
	protected static HashMap<String, String> PRIMITIVE_TYPES = new HashMap<String, String>();

	protected static HashMap<String, String> JAVA_TYPES = new HashMap<String, String>();

	static {
		PRIMITIVE_TYPES.put("base64Binary", "edu.isistan.wsqbe.matching.adapters.ByteArrayAdapter");
		PRIMITIVE_TYPES.put("boolean", "edu.isistan.wsqbe.matching.adapters.BooleanAdapter");
		PRIMITIVE_TYPES.put("byte", "edu.isistan.wsqbe.matching.adapters.ByteAdapter");
		PRIMITIVE_TYPES.put("unsignedByte", "edu.isistan.wsqbe.matching.adapters.ByteAdapter");
		PRIMITIVE_TYPES.put("dateTime", "edu.isistan.wsqbe.matching.adapters.DateTimeAdapter");
		PRIMITIVE_TYPES.put("decimal", "edu.isistan.wsqbe.matching.adapters.DecimalAdapter");
		PRIMITIVE_TYPES.put("double", "edu.isistan.wsqbe.matching.adapters.DoubleAdapter");
		PRIMITIVE_TYPES.put("float", "edu.isistan.wsqbe.matching.adapters.FloatAdapter");
		PRIMITIVE_TYPES.put("hexBinary", "edu.isistan.wsqbe.matching.adapters.ByteArrayAdapter");
		PRIMITIVE_TYPES.put("int", "edu.isistan.wsqbe.matching.adapters.IntegerAdapter");
		PRIMITIVE_TYPES.put("unsignedInt", "edu.isistan.wsqbe.matching.adapters.IntegerAdapter");
		PRIMITIVE_TYPES.put("integer", "edu.isistan.wsqbe.matching.adapters.IntegerAdapter");
		PRIMITIVE_TYPES.put("long", "edu.isistan.wsqbe.matching.adapters.LongAdapter");
		PRIMITIVE_TYPES.put("QName", "edu.isistan.wsqbe.matching.adapters.QNameAdapter");
		PRIMITIVE_TYPES.put("short", "edu.isistan.wsqbe.matching.adapters.ShortAdapter");
		PRIMITIVE_TYPES.put("unsignedShort", "edu.isistan.wsqbe.matching.adapters.ShortAdapter");
		PRIMITIVE_TYPES.put("string", "edu.isistan.wsqbe.matching.adapters.StringAdapter");
		PRIMITIVE_TYPES.put("anyType", "edu.isistan.wsqbe.matching.adapters.AnyTypeAdapter");
			
		JAVA_TYPES.put("byte[]", "edu.isistan.wsqbe.matching.adapters.ByteArrayAdapter");
		JAVA_TYPES.put("boolean", "edu.isistan.wsqbe.matching.adapters.BooleanAdapter");
		JAVA_TYPES.put("java.lang.Boolean", "edu.isistan.wsqbe.matching.adapters.BooleanAdapter");
		JAVA_TYPES.put("byte", "edu.isistan.wsqbe.matching.adapters.ByteAdapter");
		JAVA_TYPES.put("java.lang.Byte", "edu.isistan.wsqbe.matching.adapters.ByteAdapter");
		JAVA_TYPES.put("java.util.Calendar", "edu.isistan.wsqbe.matching.adapters.DateTimeAdapter");
		JAVA_TYPES.put("java.util.Date", "edu.isistan.wsqbe.matching.adapters.DateTimeAdapter");
		JAVA_TYPES.put("java.math.BigDecimal", "edu.isistan.wsqbe.matching.adapters.DecimalAdapter");
		JAVA_TYPES.put("double", "edu.isistan.wsqbe.matching.adapters.DoubleAdapter");
		JAVA_TYPES.put("java.lang.Double", "edu.isistan.wsqbe.matching.adapters.DoubleAdapter");
		JAVA_TYPES.put("float", "edu.isistan.wsqbe.matching.adapters.FloatAdapter");
		JAVA_TYPES.put("java.lang.Float", "edu.isistan.wsqbe.matching.adapters.FloatAdapter");
		JAVA_TYPES.put("int", "edu.isistan.wsqbe.matching.adapters.IntegerAdapter");
		JAVA_TYPES.put("java.lang.Integer", "edu.isistan.wsqbe.matching.adapters.IntegerAdapter");
		JAVA_TYPES.put("java.math.BigInteger", "edu.isistan.wsqbe.matching.adapters.IntegerAdapter");
		JAVA_TYPES.put("long", "edu.isistan.wsqbe.matching.adapters.LongAdapter");
		JAVA_TYPES.put("java.lang.Long", "edu.isistan.wsqbe.matching.adapters.LongAdapter");
		JAVA_TYPES.put("java.xml.QName", "edu.isistan.wsqbe.matching.adapters.QNameAdapter");
		JAVA_TYPES.put("javax.xml.namespace.QName", "edu.isistan.wsqbe.matching.adapters.QNameAdapter");
		JAVA_TYPES.put("short", "edu.isistan.wsqbe.matching.adapters.ShortAdapter");
		JAVA_TYPES.put("java.lang.Short", "edu.isistan.wsqbe.matching.adapters.ShortAdapter");
		JAVA_TYPES.put("java.lang.String", "edu.isistan.wsqbe.matching.adapters.StringAdapter");
		JAVA_TYPES.put("java.lang.Number", "edu.isistan.wsqbe.matching.adapters.NumberAdapter");

	}

	public static String getAdapterClass(DataType element) {
		return PRIMITIVE_TYPES.get(element.getType());

	}

	public static String getAdapterClass(String className) {
		return JAVA_TYPES.get(className);
	}
	
	/**
	 * Obtiene un adaptador de acuerdo a la especificacion wsdl
	 * @param element tipo wsdl
	 * @return Adaptador
	 */
	public static PrimitiveTypeAdapter getAdapter(DataType element) {
		try {
			String className = getAdapterClass(element);
			if (className!=null){
				PrimitiveTypeAdapter adapter = (PrimitiveTypeAdapter) Class.forName(className).newInstance();
				adapter.setType(element);
				return adapter;
			}	
		} catch (Exception e) {
			logger.error("Error adaptando tipo", e);
		}
		return new AnyTypeAdapter();
	}
	
	/**
	 * Obtiene un adaptador de acuerdo a la clase java
	 * @param javaClassName nombre de la clase java
	 * @param value valor del objeto java
	 * @return Adaptador
	 */
	public static PrimitiveTypeAdapter getAdpater(String javaClassName,Object value) {
		try {
			String className = getAdapterClass(javaClassName);
			PrimitiveTypeAdapter adapter = (PrimitiveTypeAdapter) Class.forName(className).newInstance();
			adapter.setValue(value);
			return adapter;
		} catch (Exception e) {
			logger.error("Error adaptando tipo", e);
		}
		return null;
	}
}
